﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SQLite;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
namespace PC_Touch.DataOP
{
    /*****通用事件管理******/

    /*****功能描述******/
    /*
   
        1. 从数据库配置表中读取事件信息，关键字段：事件名称/变量地址（PLC）/事件类型（值变化/上升沿/下降沿/目标值）
        2. 使用时   1>实例对象：EventListener listener = new EventListener();
                    2>加载事件：listener.LoadEvents();
                    3>订阅（string eventName, double value）委托类型OnTemperatureChanged方法:
                            listener.SubscribeToEvent("M32.0触发测试", OnTemperatureChanged);
                            listener.SubscribeToEvent("M1.0触发测试", OnTemperatureChanged);
                    4>监听值（double）： listener.SetValue("M32.0触发测试", 12);

    */

    public class EventManagement
    {
        public int id { get; set; }
        public string createDataTime { get; set; }
        public string eventName { get; set; }
        public string variableAddress { get; set; }
        public string variableType { get; set; }
        public string eventType { get; set; }
        public string eventValue { get; set; }
        public string remark { get; set; }
        public bool isEnable { get; set; }
    }
    public class EventManagementOP
    {
        private readonly string _connectionString;
        public EventManagementOP(string connectionString)
        {
            _connectionString = connectionString;
        }
        public void AddParameterToDatabase(EventManagement p)
        {
            using (var connection = new SQLiteConnection(_connectionString))
            {
                connection.Open();
                using (var command = new SQLiteCommand($"INSERT INTO EventManagement (eventName,variableAddress,variableType,eventType,eventValue,remark,isEnable) VALUES ('{p.eventName}','{p.variableAddress}','{p.variableType}','{p.eventType}','{p.eventValue}','{p.remark}','{p.isEnable}')", connection))
                {
                    command.ExecuteNonQuery();
                }
            }
        }
        public void UpdateParameterInDatabase(EventManagement p)
        {
            using (var connection = new SQLiteConnection(_connectionString))
            {
                connection.Open();
                using (var command = new SQLiteCommand($"UPDATE EventManagement SET eventName = '{p.eventName}', variableAddress = '{p.variableAddress}',variableType = '{p.variableType}',eventType = '{p.eventType}',eventValue='{p.eventValue}',remark='{p.remark}',isEnable='{p.isEnable}' WHERE id = {p.id}", connection))
                {
                    command.ExecuteNonQuery();
                }
            }
        }
        public void DeleteParameterFromDatabase(EventManagement p)
        {
            using (var connection = new SQLiteConnection(_connectionString))
            {
                connection.Open();
                using (var command = new SQLiteCommand($"DELETE FROM EventManagement WHERE id = {p.id}", connection))
                {
                    command.ExecuteNonQuery();
                }
            }
        }
    }
    public class EventListener
    {
        private Dictionary<string, List<Event>> eventDictionary = new Dictionary<string, List<Event>>();
        private Dictionary<string, double> previousValues = new Dictionary<string, double>();
        private Dictionary<string, double> monitoredValues = new Dictionary<string, double>();

        // 定义委托类型
        public delegate void EventHandlerDelegate(string eventName, double value);

        // 定义事件字典
        private Dictionary<string, EventHandlerDelegate> eventHandlers = new Dictionary<string, EventHandlerDelegate>();
      
        public List<EventManagement> LoadEvents()
        {
            eventDictionary.Clear();
            string connectionString = $"Data Source={AppDomain.CurrentDomain.BaseDirectory}DataBase\\app.db;Cache=Shared";
            var helper = new SQLiteHelper<EventManagement>(connectionString);
            Func<IDataRecord, EventManagement> map = record =>
                        new EventManagement
                        {
                            id = record.GetInt32(0),
                            createDataTime = record.GetString(1),
                            eventName = record.GetString(2),
                            variableAddress = record.GetString(3),
                            variableType = record.GetString(4),
                            eventType = record.GetString(5),
                            eventValue = !record.IsDBNull(6) ? record.GetString(6) : "",
                            remark = record.GetString(7),
                            isEnable = (bool)record.GetValue(8)
                        };
            var value = helper.Query("SELECT * FROM EventManagement", map);
            foreach (var item in value)
            {
                if (!eventDictionary.ContainsKey(item.eventName) && item.isEnable)
                {
                    eventDictionary[item.eventName] = new List<Event>();
                    eventDictionary[item.eventName].Add(new Event { Type = item.eventType, TargetValue = double.Parse(item.eventValue) });

                }
                else
                {
                    if (timers.ContainsKey(item.eventName))
                    {
                        timers[item.eventName].Stop();
                        timers[item.eventName].Dispose();
                        timers.Remove(item.eventName);
                    }
                }
            }
            return value;
        }
        public void MonitorValues(string key, double value)
        {
            if (eventDictionary.TryGetValue(key, out List<Event> events))
            {
                foreach (var evt in events)
                {
                    switch (evt.Type)
                    {
                        case "changeEvent":
                            TriggerEvent(key, value);
                            break;
                        case "valueEqual":
                            if (value == evt.TargetValue)
                            {
                                TriggerEvent(key, value);
                            }
                            break;
                        case "valueUp":
                            if (value > GetPreviousValue(key) && !double.IsNaN(GetPreviousValue(key)))
                            {
                                TriggerEvent(key, value);
                            }
                            break;
                        case "vlaueDown":
                            if (value < GetPreviousValue(key) && !double.IsNaN(GetPreviousValue(key)))
                            {
                                TriggerEvent(key, value);
                            }
                            break;
                        case "timerEvent":
                            HandleTimerEvent(key, value, (int)evt.TargetValue);
                            break;
                    }
                }
            }
            SetPreviousValue(key, value);
        }
        private double GetPreviousValue(string key)
        {
            if (previousValues.ContainsKey(key))
            {
                return previousValues[key];
            }
            return double.NaN;
        }
        private Dictionary<string, Timer> timers = new Dictionary<string, Timer>();

        private void HandleTimerEvent(string key, double value, int interval)
        {
            // 如果已经有定时器，停止并移除它
            if (timers.ContainsKey(key))
            {
                timers[key].Stop();
                timers[key].Dispose();
                timers.Remove(key);
            }

            // 创建新的定时器并启动
            Timer timer = new Timer(interval);
            timer.Elapsed += (sender, e) =>
            {
                TriggerEvent(key, value);
            };
            timer.AutoReset = true; // 设置为 AutoReset 以持续触发
            timer.Start();
            timers[key] = timer;
        }
        // 设置值的方法，会触发事件
        public void SetValue(string key, double value)
        {
            if (monitoredValues.TryGetValue(key, out double previousValue) && previousValue == value)
            {
                // 值没有变化，不触发事件
                return;
            }
            monitoredValues[key] = value;
            MonitorValues(key, value);
        }
        // 异步设置值的方法，会触发事件
        public async Task SetValueAsync(string key, double value)
        {
            await Task.Run(() =>
            {
                if (monitoredValues.TryGetValue(key, out double previousValue) && previousValue == value)
                {
                    return;
                }
                monitoredValues[key] = value;
                MonitorValues(key, value);
            });
        }
        private void SetPreviousValue(string key, double value)
        {
            previousValues[key] = value;
        }
        // 订阅事件的方法
        public void SubscribeToEvent(string eventName, EventHandlerDelegate handler)
        {
            if (!eventHandlers.ContainsKey(eventName))
            {
                eventHandlers[eventName] = null;
            }
            eventHandlers[eventName] += handler;
        }

        // 触发事件的方法
        private void TriggerEvent(string eventName, double value)
        {
            if (eventHandlers.TryGetValue(eventName, out EventHandlerDelegate handlers))
            {
                handlers?.Invoke(eventName, value);
            }
        }
    }
    public class Event
    {
        public string Type { get; set; }
        public double TargetValue { get; set; }
    }


}
